package dev

import (
	"awesome-devops/applications/tools"
	"awesome-devops/helper"
	"gitee.com/jjawesomejj/awesome-util/echo"
	"gitee.com/jjawesomejj/awesome-util/helper/commonhelper"
	"strings"
)

/**
为什么要有这个步骤
假如发布的服务器没有相关的构建环境
那么可以使用docker 环境来进行构建 我们则无需在服务器上安装相关的环境
此外在docker容器内运行命令更加的安全
*/
type DockerStep struct {
	//镜像名称
	DockerImage string
	//需要执行的shell
	RunShell string
	//git项目在宿主机器上的绝对路径 若程序非运行在docker环境下 则此路径就是当前项目的绝对路径
	ProjectMntDir string

	ProjectDir string

	ProjectName string
	Std         *tools.Standard
	TimeOutFunc func() (time int, echoWords string, callBack func())
}

func (step *DockerStep) SetTimeOutHandler(fun func() (time int, echoWords string, callBack func())) {
	step.TimeOutFunc = fun
}

func (step *DockerStep) SetStd(standard *tools.Standard) {
	step.Std = standard
}

//r'docker run -v /data/start/:C:\Users\zhaolijie\AppData\Local\Temp\FileSystem\project\agintw\application/7_1649676235 --name 7_1649676235 jjawesome/awesome-php-env /data/start/start.sh'
func (step *DockerStep) Run() (string, error) {
	runShell := `#!/bin/sh
executeDir=$(cd "$(dirname "$0")";pwd)
cd ${executeDir}` + "\n" + step.RunShell
	runShellName := "awesome-devops-runner-start-shell-" + commonhelper.Rand(5) + ".sh"
	containerName := "awesome-devops-runner" + strings.ReplaceAll(strings.ToLower(strings.Split(step.DockerImage, ":")[0]), "/", "_") + "-" + commonhelper.Rand(10)
	commandTemplate := "docker run -v {project_dir}:/wwwroot/applications/{project_name} --name {container_name} {docker_image} bash /wwwroot/applications/{project_name}/{run_shell_name}"
	err := commonhelper.WriteFile(step.ProjectDir+"/"+runShellName, runShell, 0777)
	if err != nil {
		return "", err
	}
	echo.Yellow(step.ProjectDir + "/" + runShellName)
	command := commonhelper.FormatJson(commandTemplate, map[string]string{
		"project_dir":    step.ProjectMntDir,
		"project_name":   step.ProjectName,
		"container_name": containerName,
		"docker_image":   step.DockerImage,
		"run_shell_name": runShellName,
	})
	command = strings.ReplaceAll(command, "//", "/")
	echo.Blue(step.ProjectMntDir)
	echo.Blue(command)
	if step.Std == nil {
		res, err := tools.GetKernelDriver().ExecShellOrBash(command, false)
		//下面开始清除容器
		_, _ = tools.GetKernelDriver().ExecShellOrBash(commonhelper.Format("docker rm {}", containerName), false)
		_ = helper.RemoveAllFile(step.ProjectDir + "/" + runShellName)
		return res, err
	} else {
		if step.TimeOutFunc != nil {
			time, echoWords, callback := step.TimeOutFunc()
			step.TimeOutFunc = func() (time1 int, echoWords1 string, callBack1 func()) {
				return time, echoWords, func() {
					_, err = tools.GetKernelDriver().ExecShellOrBashWithStdWriter(commonhelper.Format("docker rm -f {}", containerName), step.Std)
					if callback != nil {
						callback()
					}
				}
			}
		}
		res, err := tools.GetKernelDriver().ExecShellOrBashWithStdWriter(command, step.Std, step.TimeOutFunc)
		//下面开始清除容器
		_, _ = tools.GetKernelDriver().ExecShellOrBashWithStdWriter(commonhelper.Format("docker rm -f {}", containerName), step.Std)
		_ = helper.RemoveAllFile(step.ProjectDir + "/" + runShellName)
		return res, err
	}

}
